home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Programming Languages Suite
/
ProgramD2.iso
/
Borland
/
Borland C++ V5.02
/
HIERSV.PAK
/
SVRVIEW.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1997-05-06
|
29KB
|
1,130 lines
// svrview.cpp : implementation of the CServerView class
//
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992-1995 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.
#include "stdafx.h"
#include "afxdlgs.h" // for FileOpen
#include "hiersvr.h"
#include "svrdoc.h"
#include "svrview.h"
#include "svritem.h"
#include "zoomdlg.h"
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
CServerNode* NEAR CServerView::m_pDragNode = NULL;
static int ReadString(CArchive& ar, char* pString, int nMaxLen);
static BOOL FindItemRect(CDC* pDC, CServerNode* pItemFind, LPRECT lpRect,
CPoint& ptStart, CServerNode* pRoot);
static CServerNode* HitDetect(CDC* pDC, CPoint point,
CPoint& ptStart, CServerNode* pRoot);
/////////////////////////////////////////////////////////////////////////////
// support for zooming
static int NEAR rgiZoomFactor[] =
{
25, 50, 75, 100, 125, 150, 175, 200, 250, 300
};
/////////////////////////////////////////////////////////////////////////////
// CServerView
IMPLEMENT_DYNCREATE(CServerView, CScrollView)
BEGIN_MESSAGE_MAP(CServerView, CScrollView)
//{{AFX_MSG_MAP(CServerView)
ON_COMMAND(ID_CHANGE_NAME, OnChangeName)
ON_COMMAND(ID_ADD_NODE, OnAddNode)
ON_UPDATE_COMMAND_UI(ID_CHANGE_NAME, OnUpdateHasSel)
ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
ON_WM_LBUTTONDOWN()
ON_WM_RBUTTONDOWN()
ON_COMMAND(ID_IMPORT_TEXT, OnImportText)
ON_COMMAND(ID_VIEW_ZOOMCUSTOM, OnViewZoomCustom)
ON_COMMAND(ID_EDIT_CUT, OnEditCut)
ON_WM_LBUTTONDBLCLK()
ON_COMMAND(ID_EDIT_PASTE, OnEditPaste)
ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE, OnUpdateEditPaste)
ON_WM_CREATE()
ON_COMMAND(ID_EDIT_CLEAR, OnEditClear)
ON_COMMAND(ID_TREE_COLLAPSEBRANCH, OnTreeCollapsebranch)
ON_COMMAND(ID_TREE_EXPANDALL, OnTreeExpandall)
ON_COMMAND(ID_TREE_EXPANDBRANCH, OnTreeExpandbranch)
ON_COMMAND(ID_TREE_EXPANDONELEVEL, OnTreeExpandonelevel)
ON_UPDATE_COMMAND_UI(ID_TREE_COLLAPSEBRANCH, OnUpdateTreeCollapsebranch)
ON_UPDATE_COMMAND_UI(ID_TREE_EXPANDONELEVEL, OnUpdateTreeExpandonelevel)
ON_UPDATE_COMMAND_UI(ID_TREE_EXPANDALL, OnUpdateTreeExpandall)
ON_UPDATE_COMMAND_UI(ID_TREE_EXPANDBRANCH, OnUpdateTreeExpandbranch)
ON_WM_KEYDOWN()
ON_UPDATE_COMMAND_UI(ID_ADD_NODE, OnUpdateHasSel)
ON_UPDATE_COMMAND_UI(ID_EDIT_COPY, OnUpdateHasSel)
ON_UPDATE_COMMAND_UI(ID_IMPORT_TEXT, OnUpdateHasSel)
ON_UPDATE_COMMAND_UI(ID_EDIT_CUT, OnUpdateHasSel)
ON_UPDATE_COMMAND_UI(ID_EDIT_CLEAR, OnUpdateHasSel)
ON_WM_SIZE()
//}}AFX_MSG_MAP
ON_COMMAND_RANGE(ID_VIEW_ZOOM25, ID_VIEW_ZOOM300, OnZoom)
ON_UPDATE_COMMAND_UI_RANGE(ID_VIEW_ZOOM25, ID_VIEW_ZOOM300, OnUpdateZoom)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CServerView construction/destruction
CServerView::CServerView()
{
m_pSelectedNode = NULL;
m_ptStart = CPoint(CX_MARGIN, CY_MARGIN); // upper left position
// initialize zoom state (100% from size cache)
m_zoomNum = CSize(100, 100);
m_zoomDenom = CSize(100, 100);
m_prevDropEffect = DROPEFFECT_NONE;
}
CServerView::~CServerView()
{
}
/////////////////////////////////////////////////////////////////////////////
// Attributes -- public
void CServerView::SetSelection(CServerNode* pNewSel, CDC* pDC)
{
if (pNewSel == m_pSelectedNode)
return; // already set
InvalidateItem(m_pSelectedNode, pDC);
m_pSelectedNode = pNewSel;
InvalidateItem(m_pSelectedNode, pDC);
}
void CServerView::SetSelection(CServerNode* pNewSel)
{
CServerDC dc(this);
SetSelection(pNewSel, &dc);
}
/////////////////////////////////////////////////////////////////////////////
// Operations -- public
void CServerView::SetScrollInfo()
{
CServerNode* pRoot = GetDocument()->m_pRoot;
ASSERT(pRoot != NULL);
//BLOCK: determine new scrolling sizes
CSize sizeLine;
CSize sizePage;
CSize sizeTotal;
{
CServerDC dc(this);
pRoot->CalcNodeSize(&dc, sizeLine);
sizeLine.cx = sizeDefault.cx;
sizeLine.cy += CY_SEPARATOR;
sizePage.cx = sizeDefault.cx;
sizePage.cy = sizeLine.cy * 10;
// set the scroll sizes dependent on the zoom factor
dc.LPtoDP(&sizePage);
dc.LPtoDP(&sizeLine);
sizeTotal = CalcActualViewSize(&dc);
// subtract out the right and bottom margins
// these are not interesting and this way we avoid
// some problems with nonlinear scaling of fonts
CSize sizeMargin(CX_MARGIN, CY_MARGIN);
CRect rect(CPoint(0, 0), sizeMargin);
dc.LPtoDP(rect);
sizeTotal -= rect.Size();
}
SetScrollSizes(MM_TEXT, sizeTotal, sizePage, sizeLine);
}
BOOL CServerView::SetZoomFactor(CSize zoomNum, CSize zoomDenom)
{
if (zoomDenom != m_zoomDenom || zoomNum != m_zoomNum)
{
// sync to new zoom factor
m_zoomNum = zoomNum;
m_zoomDenom = zoomDenom;
// resync to new sizes
Invalidate();
return TRUE;
}
return FALSE;
}
void CServerView::UpdateServerView()
{
CServerDoc* pDoc = GetDocument();
pDoc->SetModifiedFlag();
pDoc->UpdateAllItems(NULL);
pDoc->UpdateAllViews(NULL);
}
CSize CServerView::CalcActualViewSize(CDC *pDC)
{
return CalcActualItemSize(GetDocument()->m_pRoot, pDC);
}
CSize CServerView::CalcActualItemSize(CServerNode* pItem, CDC *pDC)
{
CSize sizeTotal(0, 0);
CPoint ptStart = m_ptStart;
pItem->CalcBounding(pDC, ptStart, sizeTotal);
sizeTotal.cx += CX_MARGIN;
// sizeTotal is the extent in logical coords
// convert from logical to device
CRect rc(CPoint(0,0),sizeTotal);
pDC->LPtoDP(rc);
return rc.Size();
}
CSize CServerView::CalcScaledViewSize()
{
return CalcScaledItemSize(GetDocument()->m_pRoot);
}
CSize CServerView::CalcScaledItemSize(CServerNode* pItem)
{
CServerDC dc(this);
// set extent to 100%
dc.SetViewportExt(CSize(1,1));
dc.SetWindowExt(CSize(1,1));
CSize sizeTotal(0, 0);
CPoint ptStart = m_ptStart;
pItem->CalcBounding(&dc, ptStart, sizeTotal);
sizeTotal.cx += CX_MARGIN;
// sizeTotal is the native extent in device coords
sizeTotal.cx = MulDiv(sizeTotal.cx,m_zoomNum.cx,m_zoomDenom.cx);
sizeTotal.cy = MulDiv(sizeTotal.cy,m_zoomNum.cy,m_zoomDenom.cy);
return sizeTotal;
}
BOOL CServerView::DoPasteItem(COleDataObject* pDataObject)
{
ASSERT(pDataObject != NULL);
ASSERT_VALID(this);
ASSERT(m_pSelectedNode != NULL);
BeginWaitCursor();
TRY
{
if (pDataObject->IsDataAvailable(CServerDoc::m_cfPrivate))
DoPasteNative(pDataObject);
else if (pDataObject->IsDataAvailable(CF_TEXT))
DoPasteText(pDataObject);
else
AfxThrowNotSupportedException();
}
CATCH_ALL(e)
{
// general cleanup
TRACE0("failed to embed/link an OLE object\n");
EndWaitCursor();
return FALSE;
}
END_CATCH_ALL
EndWaitCursor();
return TRUE;
}
void CServerView::DoPasteNative(COleDataObject *pDataObject)
{
ASSERT(m_pSelectedNode != NULL);
CServerNode* pItem = new CServerNode(GetDocument());
ASSERT_VALID(pItem);
// get file refering to clipboard data
CFile *pFile = pDataObject->GetFileData(CServerDoc::m_cfPrivate);
if (pFile == NULL)
{
delete pItem;
return;
}
// connect the file to the archive and read the contents
CArchive ar(pFile, CArchive::load);
ar.m_pDocument = GetDocument(); // for COleClientItem serialize
pItem->Serialize(ar);
ar.Close();
delete pFile;
// add the item to selected node
m_pSelectedNode->m_listChild.AddHead(pItem);
SetSelection(pItem);
}
void CServerView::DoPasteText(COleDataObject *pDataObject)
{
ASSERT(m_pSelectedNode != NULL);
// get file refering to clipboard data
CFile *pFile = pDataObject->GetFileData(CF_TEXT);
if (pFile == NULL)
return;
// connect the file to the archive and read the contents
CArchive ar(pFile, CArchive::load);
DoImportText(ar);
ar.Close();
delete pFile;
}
void CServerView::DoImportText(CArchive &ar)
{
// read in lines appending items from this node
char szNode[256];
#ifdef _UNICODE
TCHAR szT[256];
#endif
int nCurLevel = 0;
CServerNode* parents[MAX_LEVEL];
parents[0] = m_pSelectedNode; // must have a parent at the current level
CServerNode* pNewSel = NULL;
while (ReadString(ar, szNode, sizeof(szNode)) != NULL)
{
int cch = strlen(szNode);
if (cch == 0)
continue;
if (szNode[cch-1] != '\n')
{
AfxMessageBox(
_T("Text file contains too long a line - aborting read\n"));
break; // leaves items loaded so far
}
szNode[cch-1] = '\0';
// check the indentation level
char* pch = szNode;
while (*pch == '\t')
pch++;
int nLevel = (pch - szNode)+1;
ASSERT(nLevel >= 1); // levels are 1 based, 0 is the root
if (*pch == '\0')
continue; // skip blank lines
if (nLevel > nCurLevel + 1 || nLevel >= MAX_LEVEL)
{
AfxMessageBox(
_T("Text file contains too many tabs = aborting read\n"));
break; // leaves items loaded so far
}
#ifdef _UNICODE
_mbstowcsz(szT, pch, sizeof(szT)/sizeof(szT[0]));
parents[nLevel] = parents[nLevel-1]->CreateChildNode(szT);
#else
parents[nLevel] = parents[nLevel-1]->CreateChildNode(pch);
#endif
nCurLevel = nLevel;
if (pNewSel == NULL)
pNewSel = parents[nLevel];
}
if (nCurLevel == 0)
return; // nothing added
SetSelection(pNewSel);
UpdateServerView();
}
void CServerView::ScrollToItem(CServerNode *pItem, BOOL bScrollUp)
{
CServerDC dc(this);
CRect rect;
CPoint ptStart = m_ptStart;
if (FindItemRect(&dc, pItem, &rect, ptStart, GetDocument()->m_pRoot))
{
CRect rc;
dc.LPtoDP(rect);
if (GetDocument()->IsInPlaceActive())
{
CRect rcPos,rcClip;
GetDocument()->GetItemPosition(&rcPos);
GetDocument()->GetItemClipRect(&rcClip);
rc.IntersectRect(&rcPos,&rcClip);
rc.OffsetRect(-rcPos.left,-rcPos.top);
if (!rc.PtInRect(rect.TopLeft()) || !rc.PtInRect(rect.BottomRight()))
{
CSize size(0, 0);
// scroll inplace site
if (bScrollUp)
size.cy = rect.top - rc.top;
else
size.cy = rect.bottom + rcPos.top - rcClip.bottom;
GetDocument()->ScrollContainerBy(size);
}
}
else
{
GetClientRect(rc);
if (!rc.PtInRect(rect.TopLeft()) || !rc.PtInRect(rect.BottomRight()))
{
CPoint ptDevScroll = GetDeviceScrollPosition();
if (bScrollUp)
ScrollToPosition(CPoint(0,rect.top + ptDevScroll.y));
else
ScrollToPosition(
CPoint(0,ptDevScroll.y + rect.bottom - rc.Height()));
}
}
}
}
void CServerView::Locate(int nCount, BOOL bScrollUp)
{
CServerNode* pRoot = GetDocument()->m_pRoot;
CServerNode* pItem = pRoot;
if (m_pSelectedNode == NULL)
SetSelection(pRoot);
if (nCount == 0) // goto top or bottom depending on direction
{
if (bScrollUp)
pItem = pRoot;
else
{
while (pItem->HasChildren())
pItem = (CServerNode *)(pItem->m_listChild.GetTail());
}
}
else if (bScrollUp)
{
pItem = m_pSelectedNode;
while (nCount--)
pItem = pRoot->GetPrev(pItem);
}
else // going down
{
pItem = m_pSelectedNode;
while (nCount--)
pItem = pRoot->GetNext(pItem);
}
ScrollToItem(pItem, bScrollUp);
SetSelection(pItem);
UpdateWindow();
}
void CServerView::InvalidateItem(CServerNode *pItem, CDC* pDC)
{
if (pItem != NULL)
{
CRect rect;
CPoint ptStart = m_ptStart;
if (FindItemRect(pDC, pItem, &rect, ptStart, GetDocument()->m_pRoot))
{
pDC->LPtoDP(rect);
InvalidateRect(rect, FALSE);
}
}
}
void CServerView::InvalidateItem(CServerNode* pItem)
{
CServerDC dc(this);
InvalidateItem(pItem, &dc);
}
void CServerView::ToggleSelectedItem()
{
if (m_pSelectedNode != NULL && m_pSelectedNode->HasChildren())
{
if (m_pSelectedNode->m_bHideChildren)
OnTreeExpandonelevel();
else
OnTreeCollapsebranch();
}
}
/////////////////////////////////////////////////////////////////////////////
// Implementation
void CServerView::OnDraw(CDC* pDC)
{
if (GetDocument()->DrawTree(pDC, m_ptStart, m_pSelectedNode) == -1)
TRACE0("Error: CServerDoc::DrawTree failed!!\n");
}
void CServerView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)
{
CScrollView::OnUpdate(pSender, lHint, pHint);
CServerDoc* pDoc = GetDocument();
CServerNode* pRoot = pDoc->m_pRoot;
ASSERT(pRoot != NULL);
if (m_pSelectedNode == NULL)
m_pSelectedNode = pRoot;
if (pDoc->IsInPlaceActive())
{
ASSERT_VALID(pDoc->m_pRoot);
CRect rect;
pDoc->GetItemPosition(rect);
// adjust rect for new size of view
rect.BottomRight() = rect.TopLeft() + CalcScaledViewSize();
pDoc->RequestPositionChange(rect);
// may resize the window before returning
}
SetScrollInfo();
}
void CServerView::OnInitialUpdate()
{
// initialize zoom state (100% from size cache)
m_zoomNum = CSize(100, 100);
m_zoomDenom = CSize(100, 100);
// call base class last (will call OnUpdate)
CScrollView::OnInitialUpdate();
}
void CServerView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
{
CScrollView::OnPrepareDC(pDC, pInfo);
pDC->SetMapMode(MM_ANISOTROPIC);
pDC->SetViewportExt(m_zoomNum);
pDC->SetWindowExt(m_zoomDenom);
}
void CServerView::SelectAtPoint(CPoint point, CPoint& pointHit)
{
CServerDC dc(this);
// change the selection as appropriate
pointHit = m_ptStart;
CServerNode* pSelection = HitDetect(&dc, point, pointHit,
GetDocument()->m_pRoot);
// now set the selection to new hit-tested node
SetSelection(pSelection, &dc);
}
void CServerView::DoBranch(CServerNode *pItem, BOOL bHide)
{
if (pItem->HasChildren())
{
pItem->m_bHideChildren = bHide;
POSITION pos = pItem->m_listChild.GetHeadPosition();
while (pos != NULL)
DoBranch((CServerNode *)pItem->m_listChild.GetNext(pos),bHide);
}
}
BOOL CServerView::OnDrop(COleDataObject* pDataObject, DROPEFFECT, CPoint)
{
ASSERT_VALID(this);
OnDragLeave();
if (DoPasteItem(pDataObject))
{
UpdateServerView();
return TRUE;
}
else
return FALSE;
}
DROPEFFECT CServerView::OnDragEnter(COleDataObject* pDataObject,
DWORD grfKeyState, CPoint point)
{
ASSERT(m_prevDropEffect == DROPEFFECT_NONE);
return OnDragOver(pDataObject, grfKeyState, point);
}
DROPEFFECT CServerView::OnDragOver(COleDataObject* pDataObject,
DWORD grfKeyState, CPoint point)
{
DROPEFFECT dropEffect = DROPEFFECT_NONE;
if (pDataObject->IsDataAvailable(CServerDoc::m_cfPrivate) ||
pDataObject->IsDataAvailable(CF_TEXT))
{
CPoint pointHit;
SelectAtPoint(point, pointHit);
UpdateWindow();
if (m_pSelectedNode != NULL)
{
// don't allow a node to drop on itself
if (m_pDragNode == m_pSelectedNode)
dropEffect = DROPEFFECT_NONE;
// if drop target is a child of drag source
// then don't drop
else if (m_pDragNode != NULL && m_pDragNode->IsChild(m_pSelectedNode))
dropEffect = DROPEFFECT_NONE;
// check for force link
#ifndef _MAC
else if ((grfKeyState & (MK_CONTROL|MK_SHIFT)) == (MK_CONTROL|MK_SHIFT))
#else
else if ((grfKeyState & (MK_OPTION|MK_SHIFT)) == (MK_OPTION|MK_SHIFT))
#endif
dropEffect = DROPEFFECT_COPY;
// check for force copy
#ifndef _MAC
else if ((grfKeyState & MK_CONTROL) == MK_CONTROL)
#else
else if ((grfKeyState & MK_OPTION) == MK_OPTION)
#endif
dropEffect = DROPEFFECT_COPY;
// check for force move
else if ((grfKeyState & MK_ALT) == MK_ALT)
dropEffect = DROPEFFECT_MOVE;
// if m_pDragNode == NULL then not dropping on self
// so make default effect be copy
// if dropping on self make default be move
else
dropEffect = (m_pDragNode == NULL) ? DROPEFFECT_COPY :
DROPEFFECT_MOVE;
}
}
m_prevDropEffect = dropEffect;
return dropEffect;
}
void CServerView::OnDragLeave()
{
m_prevDropEffect = DROPEFFECT_NONE;
}
/////////////////////////////////////////////////////////////////////////////
// CServerView commands
void CServerView::OnUpdateHasSel(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_pSelectedNode != NULL);
}
void CServerView::OnChangeName()
{
if (m_pSelectedNode != NULL && m_pSelectedNode->PromptChangeNode())
{
GetDocument()->SetModifiedFlag();
GetDocument()->UpdateAllItems(NULL);
GetDocument()->UpdateAllViews(NULL);
}
}
void CServerView::OnAddNode()
{
if (m_pSelectedNode == NULL)
AfxThrowNotSupportedException();
CServerNode* pNew;
if ((pNew = m_pSelectedNode->PromptNewChildNode()) == NULL)
return;
SetSelection(pNew);
UpdateServerView();
}
void CServerView::OnEditCopy()
{
ASSERT_VALID(this);
if (m_pSelectedNode == NULL)
return;
// get a server item suitable to generate the clipboard data
CServerItem* pItem = m_pSelectedNode->m_pServerItem;
if (pItem == NULL)
pItem = new CServerItem(GetDocument(), m_pSelectedNode);
ASSERT_VALID(pItem);
pItem->CopyToClipboard(TRUE);
}
void CServerView::OnLButtonDown(UINT, CPoint point)
{
// m_pDragNode != NULL only when drag in progress
ASSERT(m_pDragNode == NULL);
CPoint pointHit;
SelectAtPoint(point, pointHit);
UpdateWindow();
// maybe start drag drop operation on selection
if (m_pSelectedNode != NULL)
{
// record current selection because a drop back in same view
// will change the current selection
m_pDragNode = m_pSelectedNode;
// determine rectangle of object we'll be dragging
CServerDC dc(this);
CSize size = CalcActualItemSize(m_pSelectedNode, &dc);
CRect rect(pointHit, size);
// get a server item suitable to generate the clipboard data
CServerItem* pItem = m_pSelectedNode->m_pServerItem;
if (pItem == NULL)
pItem = new CServerItem(GetDocument(), m_pSelectedNode);
ASSERT_VALID(pItem);
// rect must be in screen co-ordinates
dc.LPtoDP(&rect);
CPoint ptOffset = point - rect.TopLeft();
ClientToScreen(&rect);
// drag the object
if (pItem->DoDragDrop(rect, ptOffset, TRUE,
DROPEFFECT_COPY | DROPEFFECT_MOVE) == DROPEFFECT_MOVE)
{
// the object was moved, need to delete/move depending on dest
CServerDoc* pDoc = GetDocument();
if (m_pSelectedNode == m_pDragNode)
SetSelection(pDoc->m_pRoot->GetPrev(m_pSelectedNode));
if (m_pDragNode == pDoc->m_pRoot)
pDoc->m_pRoot->InitRootNode();
else
pDoc->m_pRoot->FindAndDelete(m_pDragNode);
// if drop was not back in same view clear selected node
UpdateServerView();
}
m_pDragNode = NULL;
}
}
void CServerView::OnRButtonDown(UINT /*nFlags*/, CPoint point)
{
// make sure window is active
GetParentFrame()->ActivateFrame();
CPoint pointHit;
SelectAtPoint(point, pointHit); // select node first
UpdateWindow();
int iSub;
if (m_pSelectedNode == NULL ||
(iSub = m_pSelectedNode->GetPopupMenuIndex()) == -1)
return; // nothing if no selection or no popup
CMenu popups;
if (!popups.LoadMenu(IDR_POPUPS))
AfxThrowResourceException();
CMenu* pMenu = popups.GetSubMenu(iSub);
ASSERT(pMenu != NULL);
ClientToScreen(&point);
pMenu->TrackPopupMenu(TPM_CENTERALIGN | TPM_RIGHTBUTTON,
point.x, point.y, AfxGetMainWnd());
}
void CServerView::OnImportText()
{
if (m_pSelectedNode == NULL)
AfxThrowNotSupportedException();
CFileDialog dlg(TRUE, _T("txt"), NULL,
OFN_FILEMUSTEXIST | OFN_HIDEREADONLY,
#ifdef _MAC
_T("Text Files|TEXT|All Files|****||"));
#else
_T("Text Files (*.txt)|*.txt|All Files (*.*)|*.*||"));
#endif
if (dlg.DoModal() != IDOK)
return; // stay with old data file
CFile file;
if (!file.Open(dlg.GetPathName(), CFile::modeRead))
{
AfxMessageBox(_T("Failed to open text file"));
return;
}
CArchive ar(&file,CArchive::load);
DoImportText(ar);
ar.Close();
file.Close();
}
static int ReadString(CArchive& ar, char* pString, int nMaxLen)
{
int nCount = 0;
char ch;
pString[nCount] = (char)0;
TRY
{
do
{
ar >> (BYTE&)ch;
// watch out for ^Z (EOF under DOS)
if (ch == 0x1A)
break;
// combine "\r\n" pair into single "\n"
if (ch == '\n' && nCount != 0 && pString[nCount-1] == '\r')
nCount--;
pString[nCount++] = ch;
} while (nCount < nMaxLen-1 && ch != '\n');
}
END_TRY
#ifdef _OLD
// insert newline if missing
if (nCount != 0 && pString[nCount-1] != '\n' && nCount < nMaxLen-1)
pString[nCount++] = '\n';
pString[nCount] = (char)0;
#else
// insert newline if missing
if (nCount != 0 && pString[nCount-1] != '\n' && nCount < nMaxLen-1)
{
if (pString[nCount-1] == '\0')
pString[nCount-1] = '\n';
else
pString[nCount++] = '\n';
}
pString[nCount] = (char)0;
#endif
return nCount;
}
/////////////////////////////////////////////////////////////////////////////
// Zooming user interface
void CServerView::OnZoom(UINT nID)
{
ASSERT(nID >= ID_VIEW_ZOOM25 && nID <= ID_VIEW_ZOOM300);
CSize zoomDenom;
CSize zoomNum;
// all of our zoom factors use denominator of 100
zoomDenom.cx = 100;
zoomDenom.cy = 100;
// get zoom factor numerator and set it
ASSERT(nID-ID_VIEW_ZOOM25 < sizeof(rgiZoomFactor)/sizeof(rgiZoomFactor[0]));
int iZoomFactor = rgiZoomFactor[nID-ID_VIEW_ZOOM25];
zoomNum.cx = iZoomFactor;
zoomNum.cy = iZoomFactor;
// change the zoom factor to new zoom factor
SetZoomFactor(zoomNum, zoomDenom);
SetScrollInfo();
}
void CServerView::OnUpdateZoom(CCmdUI* pCmdUI)
{
UINT nID = pCmdUI->m_nID;
if (m_zoomDenom.cx == 100 && m_zoomDenom.cy == 100 &&
nID != ID_VIEW_ZOOMCUSTOM)
{
ASSERT(nID-ID_VIEW_ZOOM25 <
sizeof(rgiZoomFactor)/sizeof(rgiZoomFactor[0]));
int iZoomFactor = rgiZoomFactor[nID-ID_VIEW_ZOOM25];
if (iZoomFactor == m_zoomNum.cx && iZoomFactor == m_zoomNum.cy)
{
pCmdUI->SetCheck(TRUE);
return;
}
}
// default to not checked
pCmdUI->SetCheck(FALSE);
}
void CServerView::OnViewZoomCustom()
{
// prepare dialog data
CZoomDlg dlg;
dlg.m_zoomX = m_zoomNum.cx;
dlg.m_zoomY = m_zoomNum.cy;
// launch dialog
if (dlg.DoModal() == IDOK)
{
// set new zoom factors
CSize zoomNum(dlg.m_zoomX, dlg.m_zoomY);
SetZoomFactor(zoomNum, m_zoomDenom);
SetScrollInfo();
}
}
/////////////////////////////////////////////////////////////////////////////
void CServerView::OnEditCut()
{
ASSERT(m_pSelectedNode != NULL);
CServerDoc* pDoc = GetDocument();
OnEditCopy();
if (m_pSelectedNode == pDoc->m_pRoot)
pDoc->m_pRoot->InitRootNode();
else if (pDoc->m_pRoot->FindAndDelete(m_pSelectedNode))
m_pSelectedNode = NULL;
UpdateServerView();
}
void CServerView::OnLButtonDblClk(UINT /*nFlags*/, CPoint point)
{
CPoint pointHit;
SelectAtPoint(point, pointHit);
ToggleSelectedItem();
}
void CServerView::OnEditPaste()
{
COleDataObject clipboardData;
clipboardData.AttachClipboard();
DoPasteItem(&clipboardData);
UpdateServerView();
}
void CServerView::OnUpdateEditPaste(CCmdUI* pCmdUI)
{
// determine if private or standard OLE formats are on the clipboard
COleDataObject dataObj;
BOOL bEnable = m_pSelectedNode != NULL &&
dataObj.AttachClipboard() &&
(dataObj.IsDataAvailable(CServerDoc::m_cfPrivate) ||
dataObj.IsDataAvailable(CF_TEXT));
// enable command based on availability
pCmdUI->Enable(bEnable);
}
int CServerView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CScrollView::OnCreate(lpCreateStruct) == -1)
return -1;
// register drop target
m_dropTarget.Register(this);
// setup scroll state so it is possible to calculate the extent
SetScrollSizes(MM_TEXT, CSize(0, 0));
return 0;
}
void CServerView::OnEditClear()
{
CServerNode* pRoot = GetDocument()->m_pRoot;
if (m_pSelectedNode == NULL)
return;
if (m_pSelectedNode == pRoot)
pRoot->InitRootNode();
else
{
CServerNode *pItem = pRoot->GetPrev(m_pSelectedNode);
if (pRoot->FindAndDelete(m_pSelectedNode))
m_pSelectedNode = pRoot->GetNext(pItem);
}
UpdateServerView();
}
void CServerView::OnTreeCollapsebranch()
{
DoBranch(m_pSelectedNode,TRUE);
UpdateServerView();
}
void CServerView::OnTreeExpandall()
{
DoBranch(GetDocument()->m_pRoot,FALSE);
UpdateServerView();
}
void CServerView::OnTreeExpandbranch()
{
DoBranch(m_pSelectedNode,FALSE);
UpdateServerView();
}
void CServerView::OnTreeExpandonelevel()
{
if (m_pSelectedNode->HasChildren())
{
m_pSelectedNode->m_bHideChildren = FALSE;
UpdateServerView();
}
}
void CServerView::OnUpdateTreeCollapsebranch(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_pSelectedNode != NULL && m_pSelectedNode->HasChildren() &&
!m_pSelectedNode->m_bHideChildren);
}
void CServerView::OnUpdateTreeExpandonelevel(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_pSelectedNode != NULL && m_pSelectedNode->HasChildren() &&
m_pSelectedNode->m_bHideChildren);
}
void CServerView::OnUpdateTreeExpandall(CCmdUI* pCmdUI)
{
pCmdUI->Enable(GetDocument()->m_pRoot != NULL &&
GetDocument()->m_pRoot->HasChildren());
}
void CServerView::OnUpdateTreeExpandbranch(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_pSelectedNode != NULL && m_pSelectedNode->HasChildren());
}
void CServerView::OnKeyDown(UINT nChar, UINT /*nRepCnt*/, UINT /*nFlags*/)
{
switch (nChar)
{
case VK_RETURN:
ToggleSelectedItem();
break;
case VK_UP:
Locate(1, TRUE);
break;
case VK_DOWN:
Locate(1, FALSE);
break;
case VK_HOME:
Locate(0, TRUE);
break;
case VK_END:
Locate(0, FALSE);
break;
case VK_PRIOR:
Locate(10, TRUE);
break;
case VK_NEXT:
Locate(10, FALSE);
break;
}
}
void CServerView::OnSize(UINT nType, int cx, int cy)
{
// update scroll bar size before handling the size message
// (this avoids multiple updates during in-place activation)
SetScrollInfo();
CScrollView::OnSize(nType, cx, cy);
}
/////////////////////////////////////////////////////////////////////////////
// CServerDC class -- helper for setting up and cleaning up DC
CServerDC::CServerDC(CServerView *pView) : CClientDC(pView)
{
pView->OnPrepareDC(this);
pOldFont = pView->GetDocument()->SelectDocFont(this, font);
}
CServerDC::~CServerDC()
{
if (pOldFont != NULL)
SelectObject(pOldFont);
}
/////////////////////////////////////////////////////////////////////////////
// non-member static functions
// calculate the bounding rect for a given item in the context of this view
static BOOL FindItemRect(CDC* pDC, CServerNode* pItemFind, LPRECT lpRect,
CPoint& ptStart, CServerNode* pRoot)
{
ASSERT(pItemFind != NULL);
ASSERT(lpRect != NULL);
ASSERT(pRoot != NULL);
CSize sizeNode;
pRoot->CalcNodeSize(pDC, sizeNode);
if (pItemFind == pRoot)
{
// item rect does not include separator
lpRect->right = (lpRect->left = ptStart.x) + sizeNode.cx;
lpRect->bottom = (lpRect->top = ptStart.y) + sizeNode.cy;
return TRUE;
}
CPoint pt(CX_INDENT, CY_SEPARATOR);
ptStart.x += CX_INDENT; // not essential for calculation
ptStart.y += sizeNode.cy + CY_SEPARATOR;
// check the kids
if (!pRoot->m_bHideChildren)
{
POSITION pos = pRoot->m_listChild.GetHeadPosition();
while (pos != NULL)
{
CServerNode* pChild = (CServerNode*) (pRoot->m_listChild.GetNext(pos));
if (FindItemRect(pDC, pItemFind, lpRect, ptStart, pChild))
return TRUE; // found
}
}
ptStart.x -= CX_INDENT;
return FALSE;
}
// calculate the bounding rect for a given item in the context of this view
static CServerNode* HitDetect(CDC* pDC, CPoint point,
CPoint& ptStart, CServerNode* pRoot)
{
ASSERT(pRoot != NULL);
CSize sizeNode;
pRoot->CalcNodeSize(pDC, sizeNode);
CRect rect(ptStart, sizeNode);
pDC->LPtoDP(rect);
if (rect.PtInRect(point))
return pRoot;
ptStart.x += CX_INDENT;
ptStart.y += sizeNode.cy + CY_SEPARATOR;
CPoint pt = ptStart;
pDC->LPtoDP(&pt);
if (pt.y >= point.y)
return FALSE; // no point in looking any lower
// check the kids
if (!pRoot->m_bHideChildren)
{
POSITION pos = pRoot->m_listChild.GetHeadPosition();
while (pos != NULL)
{
CServerNode* pChild = (CServerNode*) (pRoot->m_listChild.GetNext(pos));
CServerNode* pItem = HitDetect(pDC, point, ptStart, pChild);
if (pItem != NULL)
return pItem; // found
}
}
ptStart.x -= CX_INDENT;
return NULL;
}
/////////////////////////////////////////////////////////////////////////////
// CServerView diagnostics
#ifdef _DEBUG
void CServerView::AssertValid() const
{
CScrollView::AssertValid();
}
void CServerView::Dump(CDumpContext& dc) const
{
CScrollView::Dump(dc);
}
#endif //_DEBUG